package wangjg.dbfx.mapping;

import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

/**
 * 映射数据集
 * @author wangjg
 *
 */
public class ResultMapping{
	public static final int REFER_COLUMN_NAME = 1;
	public static final int REFER_FIELD_NAME = 2;
	public static final int REFER_ALL = 3;
	
	private EntityInfoManager ef ;
	
	public ResultMapping(EntityInfoManager ef) {
		this.ef = ef;
	}
	
	public Object toBean(ResultSet rs, Class<?> c) throws SQLException{
		if(rs != null&&rs.next()){
			EntityInfo ei = this.getEntityInfo(c);
			try {
				Object bean = c.newInstance();
				this.fillBeanByRs(bean, rs, ei, REFER_ALL);
				return bean;
			} catch (Exception e) {
				throw new RuntimeException(e);
			}
		}else{
			return null;
		}
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public List toBeanList(ResultSet rs, Class<?> c) throws SQLException{
		ArrayList list = new ArrayList();
		EntityInfo ei = this.getEntityInfo(c);
		while(rs.next()){
			try {
				Object bean = c.newInstance();
				this.fillBeanByRs(bean, rs, ei, REFER_ALL);
				list.add(bean);
			} catch (Exception e) {
				throw new RuntimeException(e);
			}
		}
		return list;
	}
	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static List ppToList(ResultSet rs, String name) throws SQLException{
		ArrayList list = new ArrayList();
		while(rs.next()){
			try {
				list.add(rs.getObject(name));
			} catch (Exception e) {
				throw new RuntimeException(e);
			}
		}
		return list;
	}

	/**
	 * 
	 * @param bean
	 * @param rs
	 * @param referColumnName 赋值对应关系,true rs赋值给对应相同columnName的字段，false赋值给fieldName和rs columnName相同的字段。
	 * @throws SQLException
	 */
	private void fillBeanByRs(Object bean, ResultSet rs, EntityInfo ei, int refer) throws SQLException{
		Map<String, FieldInfo> fmap = ei.getFieldMap();
		Map<String, FieldInfo> cmap = ei.getColumnMap();
		ResultSetMetaData rsm = rs.getMetaData();
		for(int i=1;i<=rsm.getColumnCount();i++){
			String columnName = rsm.getColumnName(i);
			columnName = columnName.toUpperCase();
			Object columnValue = rs.getObject(i);
			try {
				FieldInfo fi = null;
				if(refer==REFER_COLUMN_NAME){
					fi = cmap.get(columnName);
				}else if(refer==REFER_FIELD_NAME){
					fi = fmap.get(columnName);
				}else if(refer==REFER_ALL){
					fi = fmap.get(columnName);
					if(fi==null)
						fi = cmap.get(columnName);
				}
				if(fi==null)
					continue;
				fi.getWriteMethod().invoke(bean, new Object[]{columnValue});
			} catch (Exception e) {
				throw new RuntimeException(e);
			}
		}
	}
	@SuppressWarnings("unused")
	private void __fillBean(Object bean,EntityInfo ei,ResultSet rs) throws SQLException{
		Map<String, FieldInfo> columns = ei.getColumnMap();
		Set<Entry<String,FieldInfo>> columnsEntrySet = columns.entrySet();
		for (Entry<String, FieldInfo> entry : columnsEntrySet) {
			String columnName = entry.getKey();
			Object columnValue = rs.getObject(columnName);
			FieldInfo fi = entry.getValue();
			try {
				fi.getWriteMethod().invoke(bean, new Object[]{columnValue});
			} catch (Exception e) {
				throw new RuntimeException(e);
			}
		}
	}

	private EntityInfo getEntityInfo(Class<?> c){
		return ef.getEntityInfo(c);
	}
}
